package com.kermitye.treenodelib

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import java.util.*

/**
 * 树节点多级列表适配器
 *
 * @param <T> 泛型，树节点数据的泛型
</T> */
open class TreeNodeAdapter<T>(// 上下文
    protected var context: Context,
    var rootTreeNodeList: List<TreeNode<T>> // 所有树节点
) : RecyclerView.Adapter<BaseViewHolder>() {
    // 视图渲染器
    private val layoutInflater: LayoutInflater
    private val treeNodeDelegateList: MutableList<TreeNodeDelegate<T>> = ArrayList() // 所有布局类型

    // 当前显示的树节点
    private val showTreeNodeList: MutableList<TreeNode<T>> = ArrayList<TreeNode<T>>()


    /**
     * 构造器
     *
     * @param context  上下文
     * @param rootList 树节点根列表（所有数据）
     */
    init {
        layoutInflater = LayoutInflater.from(context)
//        rootTreeNodeList = rootList
        init()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
        val holder = treeNodeDelegateList[viewType]
        val itemView: View = layoutInflater.inflate(holder.layoutId, parent, false)
        return BaseViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
        val viewType = getItemViewType(position)
        val delegate = treeNodeDelegateList[viewType]
        delegate.convert(holder, showTreeNodeList[position])
    }


    override fun getItemCount(): Int {
        return showTreeNodeList.size
    }

    override fun getItemViewType(position: Int): Int {
        val treeNode: TreeNode<T>? = showTreeNodeList[position]
        for (i in treeNodeDelegateList.indices) {
            val type = treeNodeDelegateList[i]
            //            if (type.isItemType(treeNode)) {
            if (type.levelTag == treeNode?.getLevel()) {
                return type.levelTag
            }
        }
        throw IllegalArgumentException("No TreeNodeDelegate added that matches position=$position in data source")
    }


    /**
     * 添加视图样式
     *
     * @param delegate 样式
     */
    fun addItemViewDelegate(delegate: TreeNodeDelegate<T>) {
        delegate.adapter = this
        treeNodeDelegateList.add(delegate)
    }

    /**
     * 移除视图样式
     *
     * @param delegate 样式
     */
    fun removeItemViewDelegate(delegate: TreeNodeDelegate<T>) {
        treeNodeDelegateList.remove(delegate)
    }


    /**
     * 刷新
     */
    fun refreshTreeNode() {
        init()
        notifyDataSetChanged()
    }

    /**
     * 初始化展开的数据
     */
    private fun init() {
        showTreeNodeList.clear()
        treeNodeDelegateList.forEach {
            it.selectTreeNodeList.clear()
        }

        refreshSelected(rootTreeNodeList)
        for (tTreeNode in rootTreeNodeList) {
            showTreeNodeList.add(tTreeNode)
            if (tTreeNode?.isExpand == true) {
                showTreeNodeList.addAll(TreeNodeHelper.getExpendedChildren(tTreeNode))
            }
        }
    }


    private fun refreshSelected(data: List<TreeNode<T>>, level: Int = 0) {
        getDelegateByLevel(level)?.let {
            it.selectTreeNodeList = data.filter { it.isSelect }.toMutableList()
            val childData = arrayListOf<TreeNode<T>>()
            data.forEach {
                if (it.hasChild()) childData.addAll(it.children!!)
            }
            refreshSelected(childData, level + 1)
        }
    }

    /**
     * 展开树节点
     *
     * @param treeNode 树节点
     */
    fun expandTreeNode(treeNode: TreeNode<T>?) {
        if (treeNode == null) return
        treeNode.isExpand = !treeNode.isExpand
        val index = showTreeNodeList.indexOf(treeNode)
        val children: List<TreeNode<T>> = TreeNodeHelper.getExpendedChildren(treeNode)
        if (index < 0 || index > showTreeNodeList.size - 1 || children == null || children.size == 0) return
        showTreeNodeList.addAll(index + 1, children)
        notifyItemRangeInserted(index + 1, children.size)
        notifyTreeNode(treeNode)
    }

    /**
     * 收缩树节点
     *
     * @param treeNode 树节点
     */
    fun collapseTreeNode(treeNode: TreeNode<T>) {
        //将子节点所有展开的都收展起来
        treeNode.children?.forEach {
            if (it.isExpand) {
                collapseTreeNode(it)
            }
        }
        treeNode.isExpand = !treeNode.isExpand
        val index = showTreeNodeList.indexOf(treeNode)
        val children: List<TreeNode<T>> =
            TreeNodeHelper.getExpendedChildren(treeNode)
        if (index < 0 || index > showTreeNodeList.size - 1 || children == null || children.size == 0) return
        showTreeNodeList.removeAll(children)
        notifyItemRangeRemoved(index + 1, children.size)
        notifyTreeNode(treeNode)
    }

    /**
     * 伸缩书记诶单
     *
     * @param treeNode 树节点
     */
    fun expandOrCollapseTreeNode(treeNode: TreeNode<T>) {
        if (treeNode.isExpand) {
            collapseTreeNode(treeNode)
        } else {
            expandTreeNode(treeNode)
        }
    }

    /**
     * 刷新树节点
     *
     * @param treeNode 树节点
     */
    fun notifyTreeNode(treeNode: TreeNode<T>) {
        val index = showTreeNodeList.indexOf(treeNode)
        if (index < 0 || index > showTreeNodeList.size - 1) return
        notifyItemChanged(showTreeNodeList.indexOf(treeNode))
    }

    /**
     * 展开所有层级的树节点
     */
    fun expandAllTreeNode() {
        TreeNodeHelper.expandAll(rootTreeNodeList)
        refreshTreeNode()
    }

    /**
     * 收缩所有层级的树节点
     */
    fun collapseAllTreeNode() {
        TreeNodeHelper.collapseAll(rootTreeNodeList)
        refreshTreeNode()
    }

    /**
     * 展开层级内的树节点
     *
     * @param level 层级
     */
    fun expandLevelTreeNode(level: Int) {
        TreeNodeHelper.expandLevel(rootTreeNodeList, level)
        refreshTreeNode()
    }

    /**
     * 根据itemType获取Delegate
     */
    fun getDelegateByLevel(level: Int): TreeNodeDelegate<T>? {
        return treeNodeDelegateList.find { it.levelTag == level }
    }

    /**
     * 获取选中的数据
     */
    fun getSelectedData(data: List<TreeNode<T>> = rootTreeNodeList): List<TreeNode<T>>? {
        var result: ArrayList<TreeNode<T>>? = null
        data.filter {
            it.isSelect
        }.onEach {
            if (result == null) {
                result = arrayListOf()
            }
            result?.add(
                TreeNode(
                    it.value,
                    it.parent,
                    it.isExpand,
                    it.isSelect,
                    if (it.hasChild()) getSelectedData(it.children!!)?.toMutableList() else null
                )
            )
        }
        return result
    }


}